home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_068 / mg1b / tty / amiga / ttyio.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  24KB  |  986 lines

  1. /*
  2.  * Name:    MicroEmacs
  3.  *        Amiga terminal-dependent I/O (Intuition)
  4.  * Last Edit:    12-Mar-87 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  5.  * Created:    21-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  6.  */
  7.  
  8. /*
  9.  * Lots of includes.
  10.  */
  11.  
  12. #include <exec/types.h>
  13. #include <exec/nodes.h>
  14. #include <exec/lists.h>
  15. #include <exec/tasks.h>
  16. #include <exec/ports.h>
  17. #include <exec/io.h>
  18. #include <devices/console.h>
  19. #include <libraries/dos.h>
  20. #include <graphics/clip.h>
  21. #include <graphics/view.h>
  22. #include <graphics/rastport.h>
  23. #include <graphics/layers.h>
  24. #include <graphics/text.h>
  25. #include <graphics/gfxbase.h>
  26. #include <intuition/intuition.h>
  27. #include <intuition/intuitionbase.h>
  28. #ifdef    CHANGE_FONT
  29. #include <libraries/diskfont.h>
  30. #endif
  31.  
  32. #undef    TRUE            /* avoid redefinition messages         */
  33. #undef    FALSE
  34. #include "def.h"        /* includes sysdef.h and ttydef.h    */
  35.  
  36. /*
  37.  * External Amiga functions.  Declared explicitly
  38.  * to avoid problems with different compilers.
  39.  */
  40. extern    LONG             AbortIO();
  41. extern    LONG             CloseDevice();
  42. extern    LONG             CloseLibrary();
  43. extern    LONG             CloseWindow();
  44. extern    struct    MsgPort        *CreatePort();
  45. extern    struct    IOStdReq    *CreateStdIO();
  46. extern    LONG             DeletePort();
  47. extern    LONG             DeleteStdIO();
  48. extern    struct    IntuiMessage    *GetMsg();
  49. extern    int             OpenConsole();
  50. extern    char            *OpenLibrary();
  51. extern    struct    Window        *OpenWindow();
  52. #ifdef    CHANGE_FONT
  53. extern    struct TextFont        *OpenDiskFont();
  54. #endif
  55. extern    LONG             RectFill();
  56. extern    LONG             ReplyMsg();
  57. extern    LONG             SetAPen();
  58. extern    LONG             SetDrMd();
  59. extern    LONG             Wait();
  60.  
  61. #ifdef    DO_MENU
  62. extern    LONG             ClearMenuStrip();    /* menu functions */
  63. extern    struct    Menu        *InitEmacsMenu();
  64. extern    struct    MenuItem    *ItemAddress();
  65. extern    LONG             SetMenuStrip();
  66. #endif
  67.  
  68. #ifdef    MANX
  69. extern    int    Enable_Abort;        /* Do NOT allow abort!        */
  70. #endif
  71.  
  72. #ifdef    LATTICE
  73. /*
  74.  * Internal functions that LATTICE wants to be void. Declare here to
  75.  *    avoid redeclaration errors.
  76.  */
  77. VOID    ttclose() ;
  78. VOID    ttputc(unsigned char) ;
  79. VOID    ttflush() ;
  80. VOID    setttysize() ;
  81. VOID    panic(char *) ;
  82. static VOID    remevt() ;
  83. static VOID    qchar(unsigned char) ;
  84. #ifdef    MOUSE
  85. static VOID    qmouse(SHORT, SHORT, USHORT) ;
  86. #endif
  87. #ifdef    DO_MENU
  88. static VOID    qmenu(USHORT) ;
  89. #endif
  90.  
  91. #else
  92. /*
  93.  * Internal functions for Manx, to avoid redeclaration errors.
  94.  */
  95. VOID    ttclose(), ttputc(), ttflush(), setttysize(), panic();
  96. static VOID    remevt(), qchar();
  97. #ifdef    MOUSE
  98. static VOID    qmouse();
  99. #endif
  100. #ifdef    DO_MENU
  101. static VOID    qmenu();
  102. #endif
  103.  
  104. #endif    LATTICE
  105.  
  106. /*
  107.  * External MicroEmacs functions and variables
  108.  */
  109. extern    int    quit();            /* Defined by "main.c"    */
  110. extern    char    *version;        /* Version information        */
  111.  
  112. /*
  113.  * Library bases (used by glue libraries)
  114.  */
  115. struct    IntuitionBase    *IntuitionBase;
  116. struct    GfxBase        *GfxBase;
  117. #ifdef    CHANGE_FONT
  118. ULONG            DiskfontBase;
  119. #endif
  120.  
  121. /*
  122.  * Intuition window and menu variables
  123.  */
  124. #define WINDOWGADGETS (WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE)
  125.  
  126. static short    borderless = TRUE;    /* Flag for borderless window    */
  127. static short    leftedge = 0,        /* Last top left position    */
  128.         topedge = 0;
  129. static short    width, height;        /* Set by ttopen()        */
  130.  
  131. struct NewWindow MicroEMACS = {
  132.     0,    0,            /* start position           */
  133.     0,    0,            /* width, height (set by ttopen)*/
  134.     0,    1,                 /* detail pen, block pen    */
  135. #ifdef    DO_MENU
  136.     MENUPICK |            /* If menu is used        */
  137. #endif
  138. #ifdef    MOUSE
  139.     MOUSEBUTTONS |             /* If mouse is used        */
  140. #endif
  141.     INTUITICKS |
  142.     CLOSEWINDOW | NEWSIZE,        /* IDCMP flags            */
  143.     0,                /* window flags    (set by ttopen)    */
  144.     NULL,                /* pointer to first user gadget */
  145.     NULL,                /* pointer to user checkmark    */ 
  146.     NULL,                /* title (filled in later)    */
  147.     NULL,                /* pointer to screen (none)    */
  148.     NULL,                /* pointer to superbitmap    */
  149.     359,101,            /* minimum size (with TOPAZ_80)    */
  150.     0, 0,                /* maximum size (set by ttopen)    */
  151.     WBENCHSCREEN            /* screen in which to open    */ 
  152. };
  153.  
  154. struct Window    *EmW;                /* Our window        */
  155. static short        toggling = FALSE;    /* Prevent menu wiping    */
  156.  
  157. #ifdef    DO_MENU
  158. static struct Menu    *EmacsMenu = NULL;    /* Our menu        */
  159. #endif
  160. #ifdef    CHANGE_FONT
  161. static    struct TextFont *EmFont = NULL;
  162. #endif
  163.  
  164. /*
  165.  * The bridge between Intuition events and Emacs' single
  166.  * input stream...
  167.  */
  168. static ULONG        class;            /* Intuition event    */
  169. static USHORT        code,            /*   information    */
  170.             qualifier;
  171. static APTR        address;
  172. static SHORT        x, y;
  173. static LONG        intuitionMsgBit;    /* Signal bit        */
  174. #define INTUITION_MESSAGE ((LONG) (1L << intuitionMsgBit))
  175.  
  176. /*
  177.  * To more thoroughly handle Intuition events, we buffer
  178.  * them into a circular queue until other routines ask
  179.  * for the information carried in them.
  180.  */
  181. #define    NIBUF    256            /* Rather roomy...        */
  182. #define    EVT_KBD        0
  183. #define    EVT_MOUSE    1
  184. #define EVT_MENU    2
  185. #define NULLEVT    ((struct event *) 0)
  186.  
  187. struct    event {
  188.     USHORT type;            /* What is it?            */
  189.     union    {
  190.         UBYTE    ch;        /* Keyboard event        */
  191.         struct {        /* Mouse click            */
  192.             SHORT row, col;    /* location in character raster    */
  193.             USHORT qualifier;
  194.         } mouse;
  195.         USHORT    code;        /* Menu event            */
  196.     } data;
  197. }        ibuf[NIBUF];        /* Input buffer            */
  198. int        ibufo, nibuf;        /* head, # of bytes in ibuf    */
  199.  
  200. /*
  201.  * Console output
  202.  */
  203. #define    CSI    0x9b            /* Command Sequence Introducer    */
  204. #define    ESC    0x1b            /* Escape key            */
  205. #define    NOBUF    512            /* About 1/4 screen        */
  206.  
  207. static struct MsgPort    *consoleWritePort;    /* I/O ports         */
  208. static struct MsgPort    *consoleReadPort;    
  209. static struct IOStdReq    *consoleWriteMsg;    /* I/O messages        */
  210. static struct IOStdReq    *consoleReadMsg;
  211. static LONG        consoleMsgBit;        /* signal bit        */
  212. #define CONSOLE_MESSAGE ((LONG) (1L << consoleMsgBit))
  213. static unsigned char    letter;            /* Console input buffer    */
  214.  
  215. static unsigned char    obuf[NOBUF];    /* Terminal output buffer    */
  216. int            nobuf;        /* # of bytes in above        */
  217. int            nrow;        /* Terminal size, rows.        */
  218. int            ncol;        /* Terminal size, columns.    */
  219. extern int        ttrow;        /* Current cursor row        */
  220.  
  221. #define    PROMPTWAIT 20            /* ticks to wait before timeout    */
  222. static    LONG        tickcount;    /* # intuiticks    since last char    */
  223.  
  224. /*
  225.  * Open up the virtual terminal MicroEMACS communicates with.
  226.  * Set up the window, console, and menu strip.
  227.  */
  228.  
  229. ttopen()
  230. {
  231.     register struct Screen *s;
  232.  
  233. #ifdef    MANX
  234.     Enable_Abort = 0;                /* Disable ^C    */
  235. #endif
  236.  
  237.     GfxBase = (struct GfxBase *)
  238.         OpenLibrary("graphics.library", (LONG) 0);
  239.     if (GfxBase  == NULL)                /* Graphics lib    */
  240.         cleanup(1);
  241.  
  242.     IntuitionBase = (struct IntuitionBase *)    /* Intuition    */
  243.         OpenLibrary("intuition.library", (LONG) 0);
  244.     if (IntuitionBase == NULL)
  245.         cleanup(2);
  246.  
  247. #ifdef    CHANGE_FONT
  248.     DiskfontBase = (ULONG) OpenLibrary("diskfont.library", (LONG)0);
  249.     if (DiskfontBase == NULL)
  250.         cleanup(21);
  251. #endif
  252.     /*
  253.      * Create our window. Set window flags based on the current
  254.      * value of the borderless flag, and the maximum size of the
  255.      * window based on the size of the first screen in the screen
  256.      * list with screen type WBENCHSCREEN (of which there had better
  257.      * be *EXACTLY* one, right???...).  To avoid possible crashes
  258.      * if user is moving screens around, turn off multitasking
  259.      * during the loop.
  260.      */
  261.     Forbid();    /* user might be moving screen */
  262.     for (s = IntuitionBase->FirstScreen; s ; s = s->NextScreen)
  263.         if ((s->Flags & SCREENTYPE) == WBENCHSCREEN)
  264.             break;
  265.     width = MicroEMACS.MaxWidth = s->Width;
  266.     height = MicroEMACS.MaxHeight = s->Height;
  267.     Permit();
  268.  
  269.     /* Set the window size based on the last one that was open,
  270.      * if it was borderless. Otherwise make it fill the screen.
  271.      * Set max/min widths based on current screen size.
  272.      *
  273.      * Set flags and window title, then open window
  274.      */
  275.     if (borderless) {
  276.         MicroEMACS.Flags = WINDOWGADGETS | ACTIVATE | BORDERLESS;
  277. #ifdef    TOGGLE_ZOOMS
  278.         MicroEMACS.LeftEdge = 0;
  279.         MicroEMACS.TopEdge = 0;
  280.         MicroEMACS.Width = MicroEMACS.MaxWidth;
  281.         MicroEMACS.Height = MicroEMACS.MaxHeight;
  282. #endif
  283.     } else {
  284.         MicroEMACS.Flags = WINDOWGADGETS | ACTIVATE | WINDOWSIZING;
  285. #ifndef    TOGGLE_ZOOMS
  286.     }
  287. #endif
  288.         MicroEMACS.LeftEdge = leftedge;
  289.         MicroEMACS.TopEdge = topedge;
  290.         MicroEMACS.Width = width;
  291.         MicroEMACS.Height = height;
  292. #ifdef    TOGGLE_ZOOMS
  293.     }
  294. #endif
  295.     MicroEMACS.Title = (UBYTE *) version;    /* name for window */
  296.     if ((EmW = OpenWindow(&MicroEMACS)) == NULL)
  297.         cleanup(3);
  298.  
  299. #ifdef    CHANGE_FONT
  300.     /* If the user requested a different font for the text, EmFont
  301.      * will be non-null, so set the font for the RastPort.  The
  302.      * conole device will pick this up when we open it later on.
  303.      */
  304.     if (EmFont)
  305.         SetFont(EmW->RPort, EmFont);
  306. #endif
  307.  
  308.     /* Once the window is created, get the Intuition signal bit,
  309.      * set up the menu, and tell the virtual terminal how big
  310.      * it is.
  311.       */
  312.     intuitionMsgBit = EmW->UserPort->mp_SigBit;
  313. #ifdef    DO_MENU
  314.     if (toggling == FALSE)
  315.         EmacsMenu = InitEmacsMenu(EmW);
  316.     SetMenuStrip(EmW, EmacsMenu);
  317. #endif
  318.     setttysize();
  319.  
  320.     /* Set up the console device.  Create the necessary read/write
  321.      * ports and messages, attach the console device thus created
  322.      * to our window, initialize the console input buffer, and
  323.      * queue the first read to the console.
  324.      */
  325.  
  326.     consoleWritePort = CreatePort("Emacs.con.write",(LONG) 0);
  327.     if (consoleWritePort == NULL)
  328.         cleanup(4);
  329.     consoleWriteMsg = CreateStdIO(consoleWritePort);
  330.     if (consoleWriteMsg == NULL)
  331.         cleanup(5);
  332.  
  333.     consoleReadPort = CreatePort("Emacs.con.read",(LONG) 0);
  334.     if (consoleReadPort == NULL)
  335.         cleanup(6);
  336.     consoleReadMsg = CreateStdIO(consoleReadPort);
  337.     if (consoleReadMsg == NULL)
  338.         cleanup(7);
  339.  
  340.     if (OpenConsole(consoleWriteMsg,consoleReadMsg,EmW) != 0)
  341.         cleanup(8);
  342.     consoleMsgBit = consoleReadPort->mp_SigBit;
  343.  
  344.     QueueRead(consoleReadMsg,&letter);
  345.     nibuf = ibufo = 0;
  346.  
  347.     return (0);
  348. }
  349.  
  350. /*
  351.  * Close the virtual terminal, aborting any
  352.  * I/O to the console device and de-allocating
  353.  * everything we have allocated.
  354.  */
  355. VOID
  356. ttclose()
  357. {
  358.     ttflush();
  359.     AbortIO(consoleReadMsg);
  360.     CloseDevice(consoleWriteMsg);
  361.     cleanup(0);
  362. #ifdef    MANX
  363.     Enable_Abort = 1;
  364. #endif
  365. }
  366.  
  367. /*
  368.  * Toggle between a borderless window
  369.  * and a sizeable window. This lets you
  370.  * use the whole screen if you want.
  371.  * Bound to "toggle-window-hack" by
  372.  * ttykbd.c
  373.  */
  374.  
  375. togglewindow(f, n, k)
  376. {
  377.     toggling = TRUE;            /* Notify the system    */
  378. #ifdef    TOGGLE_ZOOMS
  379.     if (!borderless) {
  380. #endif
  381.         leftedge = EmW->LeftEdge;    /* save window state    */
  382.         topedge = EmW->TopEdge;
  383.         width = EmW->Width;
  384.         height = EmW->Height;
  385. #ifdef    TOGGLE_ZOOMS
  386.     }
  387. #endif
  388.     ttclose();                /* reset to zero    */
  389.  
  390.     borderless = !borderless;        /* toggle window flag    */
  391.     ttopen();                /* re-open tty window    */
  392.     ttinit();                /* re-initalize tty    */
  393.     sgarbf = TRUE;                /* screen was trashed    */
  394.     nrow = ncol = -1;            /* trash screen size    */
  395.     refresh();                /* and redraw it    */
  396.     toggling = FALSE;            /* Ok, done        */
  397.     return (TRUE);
  398. }
  399.  
  400. #ifdef    CHANGE_FONT
  401. /*
  402.  * Select a different font for the Emacs window.
  403.  * This obviously does not work very well
  404.  * with proportional fonts, so we ask the
  405.  * user to confirm before he uses one.
  406.  * It's available if you want to be able
  407.  * to use your own disk font (or Topaz 11
  408.  * under 1.2) to edit with.
  409.  */
  410.  
  411. setfont(f, n, k)
  412. {
  413.     register int    s, size;
  414.     register struct TextFont *newfont;
  415.     char        fontname[80], fontpath[84], fontsize[3];
  416.     struct TextAttr    ta;
  417.  
  418.     /* Get font size */
  419.     if (f == TRUE)
  420.         size = n;
  421.     else {
  422.         if ((s = ereply("Font size: ",
  423.                 fontsize, sizeof(fontsize))) != TRUE)
  424.             return (s);
  425.         size = atoi(fontsize);
  426.     }
  427.  
  428.     if (size <= 0) {    /* reset to default font    */
  429.         if (EmFont)
  430.             CloseFont(EmFont);
  431.         EmFont = NULL;
  432.     } else {        /* user wants to set a new font name */
  433.         if ((s = ereply("Font name: ",
  434.                 fontname, sizeof(fontname))) != TRUE)
  435.             return (s);
  436.         strcpy(fontpath,fontname);
  437.         strncat(fontpath,".font",sizeof(fontpath));/* make name */
  438.  
  439.         /* set up text attributes */
  440.         ta.ta_Name = (UBYTE *)fontpath;
  441.         ta.ta_YSize = size;
  442.         ta.ta_Style = FS_NORMAL;
  443.         ta.ta_Flags = 0; /* use either */
  444.  
  445.         /* Look for the font */
  446.         ewprintf("Looking for %s %d...",fontname,size);
  447.         if ((newfont = OpenDiskFont(&ta)) == NULL) {
  448.             ewprintf("Can't find %s %d!",fontname,size);
  449.             return (FALSE);
  450.         } else { /* Found it! Check before using it. */
  451.             if ((newfont->tf_YSize != size) && ((s = eyesno(
  452.                "Size unavailable - use closest"))!=TRUE)){
  453.                 CloseFont(newfont);
  454.                 return (FALSE);
  455.             }
  456.             if ((newfont->tf_Flags & FPF_PROPORTIONAL) &&
  457.                 (((s = eyesno("Use proportional font")))!=TRUE)){
  458.                 CloseFont(newfont);
  459.                 return (FALSE);
  460.             }
  461.             /* Get rid of old font and cache the new one */
  462.             if (EmFont)
  463.                 CloseFont(EmFont);
  464.             EmFont = newfont;
  465.         }
  466.     }
  467.  
  468.     /* Now that the font is selected, close the window. */
  469.     toggling = TRUE;            /* Notify the system    */
  470.     ttclose();                /* reset to zero    */
  471.     ttopen();                /* re-open w/new font    */
  472.     ttinit();                /* re-init console    */
  473.     nrow = -1;                /* trash size        */
  474.     ncol = -1;                /* so refresh() works    */
  475.     refresh();                /* redo whole screen    */
  476.     if (size > 0)
  477.         ewprintf("Now using font %s %d",fontname,EmFont->tf_YSize);
  478.     else
  479.         ewprintf("Now using default font");
  480.     return (TRUE);
  481. }
  482. #endif
  483.  
  484. /*
  485.  * Write a single character to the screen.
  486.  * Buffered for extra speed, so ttflush()
  487.  * does all the work.
  488.  */
  489. VOID
  490. ttputc(c)
  491. unsigned char c;
  492. {
  493.     obuf[nobuf++] = c;
  494.     if (nobuf >= NOBUF)
  495.         ttflush();
  496. }
  497.  
  498. /*
  499.  * Flush characters from the output buffer.
  500.  * Just blast it out with a console write call.
  501.  */
  502. VOID
  503. ttflush()
  504. {
  505.     if (nobuf > 0) {
  506.         ConWrite(consoleWriteMsg, obuf, nobuf);
  507.         nobuf = 0;
  508.     }
  509. }
  510.  
  511. /*
  512.  * Get a character for Emacs, without echo or
  513.  * translation.
  514.  */
  515. ttgetc()
  516. {
  517.     return handle_kbd(FALSE);    /* wait for char w/o timeout */
  518. }
  519.  
  520. /*
  521.  * Return TRUE if we've waited for 2 seconds and nothing has
  522.  * happened, else return false.
  523.  */
  524.  
  525. ttwait()
  526. {
  527.     return handle_kbd(TRUE);    /* time out after 2 sec */
  528. }
  529.  
  530. /*
  531.  * Common routine for handling character input, with and
  532.  * without timeout.  Handle events until:
  533.  *
  534.  *    1) a character is put in the input buffer
  535.  *    2) if timeout == TRUE, PROMPTWAIT IntuiTicks have gone by
  536.  *
  537.  * If timeout == FALSE, the character is returned and removed from
  538.  *    the input buffer.
  539.  * If timeout == TRUE, returns TRUE if the read timed out, else FALSE.
  540.  *    I.e. FALSE indicates a character was typed before the time limit
  541.  */
  542.  
  543. static handle_kbd(timeout)
  544. register int timeout;
  545. {
  546.     register struct    IntuiMessage *message;    /* IDCMP message     */
  547.     register LONG    wakeupmask;        /* which signals?    */
  548.     register int    charfound;        /* got a character yet?    */
  549.     unsigned char    nextchar();        /* return next char evt    */
  550.  
  551.     tickcount = 0;                /* always zero the count */
  552.     if (striptochar())            /* any chars in buffer?    */
  553.         return timeout ? FALSE : ((int) (nextchar() & 0xFF));
  554.  
  555.     charfound = FALSE;            /* nope -- have to wait    */
  556.     do {
  557.         wakeupmask = Wait(INTUITION_MESSAGE|CONSOLE_MESSAGE);
  558.  
  559.         if (wakeupmask & CONSOLE_MESSAGE) {    /* keyboard     */
  560.             GetMsg(consoleReadPort);    /* free message     */
  561.             qchar(letter);            /* do this FIRST */
  562.             QueueRead(consoleReadMsg, &letter);
  563.             charfound = TRUE;
  564.         }
  565.  
  566.         /* Intuition event.  Handle Intuiticks specially. */
  567.         if (wakeupmask & INTUITION_MESSAGE)
  568.             while(message =    GetMsg(EmW->UserPort))
  569.                 if (message->Class == INTUITICKS) {
  570.                     tickcount++;
  571.                     ReplyMsg(message);
  572.                 } else if (dispatch(message) == TRUE)
  573.                     charfound = TRUE;
  574.  
  575.         /* time out if enough ticks have gone by without
  576.          * any keyboard input.  We do this *after* all the
  577.          * events in the current list have been dispatched.
  578.          */
  579.         if (timeout && (tickcount > PROMPTWAIT))
  580.             break;
  581.     } while (charfound == FALSE);
  582.  
  583.     /* If called by ttwait(), return FALSE if a character was found.
  584.      * Else return the next character in the input buffer
  585.     */
  586.     return timeout ? (!charfound) : ((int) (nextchar() & 0xFF));
  587. }
  588.  
  589. /*
  590.  * Handle the events we handle...  The result
  591.  * returned indicates if we've put a character
  592.  * in the input buffer.
  593.  */
  594. static dispatch(msg)
  595. register struct IntuiMessage *msg;
  596. {
  597. #ifdef    DO_MENU
  598.     register struct    MenuItem    *item;
  599. #endif
  600.     register int            txheight, txwidth;
  601.     register struct RastPort    *rp;
  602.     int                dx, dy, fgpen, drmode;
  603.             
  604.     class =    msg->Class;        /* grab the info before we     */
  605.     code = msg->Code;        /* reply to the message        */
  606.     qualifier = msg->Qualifier;
  607.     address = msg->IAddress;
  608.     x = msg->MouseX;
  609.     y = msg->MouseY;
  610.     ReplyMsg(msg);            /* return it to Intuition    */
  611.  
  612.     switch(class) {            /* see what the fuss is about    */
  613. #ifdef    DO_MENU
  614.     case MENUPICK:
  615.         if (code == MENUNULL)
  616.             return (FALSE);
  617.         while (code != MENUNULL) {/* handle multiple selection    */
  618.             qmenu(code);
  619.             item = ItemAddress(EmacsMenu,(LONG) code);
  620.             code = item->NextSelect;
  621.         }
  622.         return (TRUE);        /* puts <CSI>M~ in event queue    */
  623.         break;
  624. #endif
  625.  
  626. #ifdef    MOUSE
  627.     case MOUSEBUTTONS:            /* fake the mouse key    */
  628.         if (code != SELECTDOWN)        /* ignore SELECTUP    */
  629.             return (FALSE);
  630.         qmouse(x, y, qualifier);
  631.         return (TRUE);
  632.         break;
  633. #endif
  634.     case NEWSIZE:
  635.         /* Sometimes when you resize the window to make it
  636.          * smaller, garbage is left at the right and bottom
  637.          * sides of the window. This code is devoted to
  638.          * (somehow) getting rid of this garbage.  Any
  639.          * suggestions?
  640.          */
  641.  
  642.         rp = EmW->RPort;
  643.         fgpen = rp->FgPen;        /* save params        */
  644.         drmode = rp->DrawMode;
  645.         SetDrMd(rp, (LONG) JAM1);
  646.         SetAPen(rp, (LONG) EmW->RPort->BgPen);
  647.  
  648.         /* Check the bottom of the window
  649.          */
  650.         txheight = EmW->Height - EmW->BorderTop - EmW->BorderBottom;
  651.         if (dy = (txheight % FontHeight(EmW)))
  652.             RectFill(rp,
  653.                 (LONG) EmW->BorderLeft,
  654.                 (LONG) EmW->BorderTop + txheight - dy - 1,
  655.                 (LONG) (EmW->Width - 1) - EmW->BorderRight,
  656.                 (LONG) (EmW->Height - 1) - EmW->BorderBottom);
  657.  
  658.         /* Check the right side
  659.          */
  660.         txwidth = EmW->Width - EmW->BorderLeft - EmW->BorderRight;
  661.         if (dx = txwidth % FontWidth(EmW))
  662.             RectFill(rp,
  663.                 (LONG) EmW->BorderLeft + txwidth - dx - 1,
  664.                 (LONG) EmW->BorderTop,
  665.                 (LONG) (EmW->Width - 1) - EmW->BorderRight,
  666.                 (LONG) (EmW->Height - 1) - EmW->BorderBottom);
  667.  
  668.         SetDrMd(rp, (LONG) drmode);
  669.         SetAPen(rp, (LONG) fgpen);    /* restore colors */
  670.  
  671.         /* Tell the console device to resize itself */
  672.         ttputc(CSI);
  673.         ttputc('t');
  674.         ttputc(CSI);
  675.         ttputc('u');
  676.         ttflush();
  677.  
  678.         /* Signal the editor that a new size has occurred */
  679.         qchar(ESC);
  680.         qchar('\f');
  681.  
  682.         return (TRUE);            /* we done (finally)    */
  683.         break;
  684.  
  685.         case CLOSEWINDOW:            /* Call quit() directly    */
  686.         quit(FALSE, 1, KRANDOM);
  687.         return (FALSE);
  688.                 break;
  689.  
  690.     default:
  691.         panic("HandleMsg: unknown event!!!");
  692.         break;
  693.     }
  694.     return(FALSE);
  695. }
  696.  
  697. #ifdef    DO_MENU
  698. /*
  699.  * Return the next menu selection number to
  700.  * the caller.  Used by "ttymenu.c".
  701.  */
  702. ttmenu(codep)
  703. USHORT *codep;
  704. {
  705.     register struct event *e;
  706.     struct event *nextevt();
  707.  
  708.     e = nextevt();
  709.     if (e->type != EVT_MENU)
  710.         return (FALSE);
  711.  
  712.     *codep = e->data.code;
  713.     remevt();            /* remove event by hand    */
  714.     return (TRUE);
  715. }
  716. #endif
  717.  
  718. #ifdef    MOUSE
  719. /*
  720.  * Return the next mouse click values to
  721.  * the caller.   *Rowp and *colp will contain
  722.  * the row and column where the mouse click occured.
  723.  * This is so that only the terminal driver has
  724.  * to know about the size of the window's font.
  725.  * If the flag argument f is FALSE, the mouse event
  726.  * is *not* removed from the queue, allowing routines
  727.  * that need to (mainly getmouse()) to peek at it.
  728.  */
  729. ttmouse(f, rowp,colp,qualp)
  730. int f;
  731. USHORT *rowp, *colp, *qualp;
  732. {
  733.     register struct event *e;
  734.     struct event *nextevt();
  735.  
  736.     e = nextevt();
  737.     if (e->type != EVT_MOUSE)
  738.         return (FALSE);        /* next isn't mouse evt */
  739.  
  740.     *colp = e->data.mouse.col;
  741.     *rowp = e->data.mouse.row;
  742.     *qualp = e->data.mouse.qualifier;
  743.     if (f)
  744.         remevt();            /* remove the event    */
  745.     return (TRUE);
  746. }
  747. #endif
  748.  
  749. /*
  750.  * Return the current size of the virtual
  751.  * terminal in nrow and ncol, making sure
  752.  * we don't go beyond the size of the internal
  753.  * video array.
  754.  * Assumes the current font is monospaced
  755.  * (not always safe bet any more :-) :-).
  756.  */
  757. VOID
  758. setttysize()
  759. {
  760.     nrow = (EmW->Height - TOP_OFFSET
  761.             - EmW->BorderBottom) / FontHeight(EmW);
  762.     ncol = (EmW->Width - EmW->BorderLeft
  763.             - EmW->BorderRight) / FontWidth(EmW);
  764.     if (nrow < 1)
  765.         nrow = 1;
  766.     if (nrow > NROW)
  767.         nrow = NROW;
  768.     if (ncol < 1)
  769.         ncol = 1;
  770.     if (ncol > NCOL)
  771.         ncol = NCOL;
  772. }
  773.  
  774. /*
  775.  * Exit as soon as possible, after displaying
  776.  * the message.
  777.  */
  778. VOID
  779. panic(s)
  780. char *s;
  781. {
  782.     ewprintf(s);        /* put message at bottom    */
  783.     Delay((ULONG) 90);    /* wait 1.5 seconds        */
  784.     ttclose();        /* get rid of window &resources    */
  785.     exit(10000);        /* go 'way            */
  786. }
  787.  
  788. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  789.  *             Event buffer management         *
  790.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  791.  
  792. /*
  793.  * If the buffer's full, crap out, else
  794.  * return a pointer to the (ibufo + nibuf)'th
  795.  * event record (mod NIBUF).  Postincrement
  796.  * nibuf so it points at the next record and
  797.  * also keeps track of how many events
  798.  * are in the buffer.
  799.  */
  800. static struct event *newevt()
  801. {
  802.     return ((nibuf < NIBUF) ? 
  803.         (ibuf + ((ibufo + nibuf++) % NIBUF)) : NULLEVT);
  804. }
  805.  
  806. /*
  807.  * Return pointer to next item in queue,
  808.  * *without* removing it.
  809.  */
  810. static struct event *nextevt()
  811. {
  812.     return (nibuf ? (ibuf + ibufo) : NULLEVT);
  813. }
  814.  
  815. /*
  816.  * Move buffer pointer to next item in queue.
  817.  */
  818. static VOID
  819. remevt()
  820. {
  821.     if (nibuf <= 0)
  822.         nibuf = 0;
  823.     else {
  824.         nibuf--;
  825.         ibufo++;
  826.         ibufo %= NIBUF;        /* wrap around in buffer    */
  827.     }
  828. }
  829.  
  830. /*
  831.  * Return true if there are some characters available
  832.  * in the buffer.  Unlike striptochar, don't do anything
  833.  * to the input buffer, just return a value.
  834.  */
  835. typeahead()
  836. {
  837.     register int bufp;
  838.  
  839.     for (bufp = 0; bufp < nibuf; bufp++)
  840.         if (ibuf[(ibufo + bufp) % NIBUF].type == EVT_KBD)
  841.             return (TRUE);
  842.     return (FALSE);
  843. }
  844.  
  845. /*
  846.  * See if there are any characters queued,
  847.  * stripping any other events that may
  848.  * be in the way.  *Don't* remove the character
  849.  * from the  queue.
  850.  */
  851. static
  852. striptochar()
  853. {
  854.     register struct event *e;
  855.  
  856.     while (e = nextevt())
  857.         if (e->type == EVT_KBD)
  858.             return (TRUE);
  859.         else
  860.             remevt();
  861.     return (FALSE);
  862. }
  863.  
  864. /*
  865.  * Return next character in event buffer.
  866.  */
  867. static unsigned char
  868. nextchar()
  869. {
  870.     register struct event *e;
  871.  
  872.     if (e = nextevt()) {
  873.         remevt();
  874.         return (e->data.ch);
  875.     }
  876.     else
  877.         return ((unsigned char) 0);    /* shouldn't happen    */
  878. }
  879.  
  880. /*
  881.  * Add a keyboard event to the queue
  882.  */
  883. static VOID
  884. qchar(c)
  885. unsigned char c;
  886. {
  887.     register struct event *e;
  888.  
  889.     if (e = newevt()) {
  890.         e->type = EVT_KBD;
  891.         e->data.ch = c;
  892.     }
  893. }
  894.  
  895. #ifdef    MOUSE
  896. /*
  897.  * Add a mouse event to the queue, calculating
  898.  * the row and column value from the current height
  899.  * and width of the window's font.
  900.  */
  901. static VOID
  902. qmouse(x, y, qual)
  903. SHORT x, y;
  904. USHORT qual;
  905. {
  906.     register struct event *e;
  907.  
  908.     qchar(CSI);
  909.     qchar('P');
  910.     qchar('~');
  911.     if (e = newevt()) {
  912.         e->type = EVT_MOUSE;
  913.         e->data.mouse.col = (x - EmW->BorderLeft) / FontWidth(EmW);
  914.         e->data.mouse.row = (y - TOP_OFFSET) / FontHeight(EmW);
  915.         e->data.mouse.qualifier = qual;
  916.     }
  917. }
  918. #endif
  919.  
  920. #ifdef    DO_MENU
  921. /*
  922.  * Add a menu key to queue
  923.  */
  924. static VOID
  925. qmenu(code)
  926. USHORT code;
  927. {
  928.     register struct event *e;
  929.  
  930.     qchar(CSI);        /* menu key sequence    */
  931.     qchar('M');
  932.     qchar('~');
  933.     if (e = newevt()) {
  934.         e->type = EVT_MENU;
  935.         e->data.code = code;
  936.     }
  937. }
  938. #endif
  939.  
  940. /*
  941.  * Clean up.
  942.  *
  943.  * Fall through all the possible cases (0 means
  944.  * get rid of everything and start with the case
  945.  * that fits the error situation).
  946.  */
  947.  
  948. static cleanup(prob)
  949. {
  950.     switch (prob) {
  951.     case 0:            /* just clean everything up
  952.     case 8:            /* couldn't open console device        */
  953.         DeleteStdIO(consoleReadMsg);
  954.     case 7:            /* couldn't get console read msg    */
  955.         DeletePort(consoleReadPort);
  956.     case 6:            /* couldn't get console read port    */
  957.         DeleteStdIO(consoleWriteMsg);
  958.     case 5:            /* couldn't get console write msg    */
  959.         DeletePort(consoleWritePort);
  960.     case 4:            /* couldn't get console write port    */
  961. #ifdef    CHANGE_FONT
  962.         if ((toggling == FALSE) && EmFont)
  963.             CloseFont(EmFont);/* access_count-- */
  964. #endif
  965. #ifdef    DO_MENU
  966.         if (toggling == FALSE) {
  967.             ClearMenuStrip(EmW);
  968.             DisposeMenus(EmacsMenu);
  969.         }
  970. #endif
  971.         CloseWindow(EmW);
  972.     case 3:            /* couldn't open window            */
  973. #ifdef    CHANGE_FONT
  974.         CloseLibrary(DiskfontBase);
  975. #endif
  976.     case 21:        /* couldn't open diskfonts        */
  977.         CloseLibrary(IntuitionBase);
  978.     case 2:            /* couldn't open Intuition        */
  979.         CloseLibrary(GfxBase);
  980.     case 1:            /* couldn't open graphics -- do nothing    */
  981.         break;
  982.     }
  983.         return(0);
  984. }
  985.  
  986.